home *** CD-ROM | disk | FTP | other *** search
/ Visual Basic Source Code / Visual Basic Source Code.iso / vbsource / minmax_1 / mssubcla.bas < prev    next >
BASIC Source File  |  1998-10-19  |  7KB  |  187 lines

  1. Attribute VB_Name = "MSubclass"
  2.   Option Explicit
  3.   ' A demo project showing how to prevent the user from making a window smaller
  4.   ' or larger than you want them to through subclassing the WM_GETMINMAXINFO message.
  5.   ' by Bryan Stafford of New Vision Software« - newvision@imt.net
  6.   ' this demo is released into the public domain "as is" without
  7.   ' warranty or guaranty of any kind.  In other words, use at
  8.   ' your own risk.
  9.   
  10.   ' See the comments at the end of this module for a brief explaination of
  11.   ' what subclassing is.
  12.   
  13.   Type POINTAPI
  14.     x As Long
  15.     y As Long
  16.   End Type
  17.  
  18.   ' the message we will subclass
  19.   Public Const WM_GETMINMAXINFO As Long = &H24
  20.  
  21.   Type MINMAXINFO
  22.     ptReserved As POINTAPI
  23.     ptMaxSize As POINTAPI
  24.     ptMaxPosition As POINTAPI
  25.     ptMinTrackSize As POINTAPI
  26.     ptMaxTrackSize As POINTAPI
  27.   End Type
  28.  
  29.  
  30.   ' this var will hold a pointer to the original message handler so we MUST
  31.   ' save it so that it can be restored before we exit the app.  if we don't
  32.   ' restore it.... CRASH!!!!
  33.   Public procOld As Long
  34.   
  35.   ' declarations of the API functions used
  36.   Public Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (lpDest As Any, lpSource As Any, _
  37.                                                                                           ByVal cBytes&)
  38.                                                                                           
  39.   Public Declare Function CallWindowProc& Lib "user32" Alias "CallWindowProcA" (ByVal lpPrevWndFunc&, _
  40.                                                     ByVal hWnd&, ByVal Msg&, ByVal wParam&, ByVal lParam&)
  41.   
  42. 'WARNING!!!! WARNING!!!! WARNING!!!! WARNING!!!! WARNING!!!! WARNING!!!!
  43. '
  44. ' Do NOT try to step through this function in debug mode!!!!
  45. ' You WILL crash!!!  Also, do NOT set any break points in this function!!!
  46. ' You WILL crash!!!  Subclassing is non-trivial and should be handled with
  47. ' EXTREME care!!!
  48. '
  49. ' There are ways to use a "Debug" dll to allow you to set breakpoints in
  50. ' subclassed code in the IDE but this was not implimented for this demo.
  51. '
  52. 'WARNING!!!! WARNING!!!! WARNING!!!! WARNING!!!! WARNING!!!! WARNING!!!!
  53.   
  54. Public Function WindowProc(ByVal hWnd As Long, ByVal iMsg As Long, _
  55.                                               ByVal wParam As Long, ByVal lParam As Long) As Long
  56.     
  57.   ' this is *our* implimentation of the message handling routine
  58.   
  59.   ' determine which message was recieved
  60.   Select Case iMsg
  61.     
  62.     Case WM_GETMINMAXINFO
  63.       ' dimention a variable to hold the structure passed from Windows in lParam
  64.       Dim udtMINMAXINFO As MINMAXINFO
  65.       Dim nWidthPixels&, nHeightPixels&
  66.       
  67.       nWidthPixels = Screen.Width \ Screen.TwipsPerPixelX
  68.       nHeightPixels = Screen.Height \ Screen.TwipsPerPixelY
  69.       
  70.       ' copy the struct to our UDT variable
  71.       CopyMemory udtMINMAXINFO, ByVal lParam, 40&
  72.            
  73.       With udtMINMAXINFO
  74.         ' set the width of the form when it's maximized
  75.         .ptMaxSize.x = nWidthPixels - (nWidthPixels \ 4)
  76.         ' set the height of the form when it's maximized
  77.         .ptMaxSize.y = nHeightPixels - (nHeightPixels \ 4)
  78.         
  79.         ' set the Left of the form when it's maximized
  80.         .ptMaxPosition.x = nWidthPixels \ 8
  81.         ' set the Top of the form when it's maximized
  82.         .ptMaxPosition.y = nHeightPixels \ 8
  83.         
  84.         ' set the max width that the user can drag the form
  85.         .ptMaxTrackSize.x = .ptMaxSize.x
  86.         ' set the max height that the user can drag the form
  87.         .ptMaxTrackSize.y = .ptMaxSize.y
  88.         
  89.         ' set the min width that the user can drag the form
  90.         .ptMinTrackSize.x = nWidthPixels \ 4
  91.         ' set the min width that the user can drag the form
  92.         .ptMinTrackSize.y = nHeightPixels \ 4
  93.       End With
  94.            
  95.       ' copy our modified struct back to the Windows struct
  96.       CopyMemory ByVal lParam, udtMINMAXINFO, 40&
  97.   
  98.       ' return zero indicating that we have acted on this message
  99.       WindowProc = False
  100.       
  101.       ' exit the function without letting VB get it's grubby little hands on the message
  102.       Exit Function
  103.       
  104.   End Select
  105.   
  106.   ' pass all messages on to VB and then return the value to windows
  107.   WindowProc = CallWindowProc(procOld, hWnd, iMsg, wParam, lParam)
  108.  
  109. End Function
  110.  
  111. ' What is subclassing anyway?
  112. '
  113. ' Windows runs on "messages".  A message is a unique value that, when
  114. ' recieved by a window or the operating system, tells either that
  115. ' something has happened and that an action of some sort needs to be
  116. ' taken.  Sort of like your nervous system passing feeling messages
  117. ' to your brain and the brain passing movement messages to your body.
  118. '
  119. ' So, each window has what's called a message handler.  This is a
  120. ' function where all of the messages FROM Windows are recieved.  Every
  121. ' window has one.  I mean EVERY window.  That means every button, textbox,
  122. ' picturebox, form, etc...  Windows keeps track of where the message
  123. ' handler (called a WindowProc [short for PROCedure]) in a "Class"
  124. ' structure associated with each window handle (otherwise known as hWnd).
  125. '
  126. ' What happens when a window is subclassed is that you insert a new
  127. ' window procedure in line with the original window procedure.  In other
  128. ' words, Windows sends the messages for the given window to YOUR WindowProc
  129. ' FIRST where you are responsible for handling any messages you want to
  130. ' handle.  Then you MUST pass the remaining messages on to the default
  131. ' WindoProc.  So it looks like this:
  132. '
  133. '  Windows Message Sender --> Your WindowProc --> Default WindowProc
  134. '
  135. ' A window can be subclassed MANY times so it could look like this:
  136. '
  137. '  Windows Message Sender --> Your WindowProc --> Another WindowProc _
  138. '  --> Yet Another WindowProc --> Default WindowProc
  139. '
  140. ' You can also change the order of when you respond to a message by
  141. ' where in your routine you pass the message on to the default WindowProc.
  142. ' Let's say that you want to draw something on the window AFTER the
  143. ' default WindowProc handles the WM_PAINT message.  This is easily done
  144. ' by calling the default proc before you do your drawing.   Like so:
  145. '
  146. ' Public Function WindowProc(Byval hWnd, Byval etc....)
  147. '
  148. '   Select Case iMsg
  149. '     Case SOME_MESSAGE
  150. '       DoSomeStuff
  151. '
  152. '     Case WM_PAINT
  153. '       ' pass the message to the defproc FIRST
  154. '       WindowProc = CallWindowProc(procOld, hWnd, iMsg, wParam, lParam)
  155. '
  156. '       DoDrawingStuff ' <- do your drawing
  157. '
  158. '       Exit Function ' <- exit since we already passed the
  159. '                     '    measage to the defproc
  160. '
  161. '   End Select
  162. '
  163. '   ' pass all messages on to VB and then return the value to windows
  164. '   WindowProc = CallWindowProc(procOld, hWnd, iMsg, wParam, lParam)
  165. '
  166. ' End Function
  167. '
  168. '
  169. ' This is just a basic overview of subclassing but I hope it helps if
  170. ' you were fuzzy about the subject before reading this.
  171. '
  172.  
  173.  
  174.  
  175.  
  176.  
  177.  
  178.  
  179.  
  180.  
  181.  
  182.  
  183.  
  184.  
  185.  
  186.  
  187.